﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using HslCommunication.Profinet;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.Profinet.Omron;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using System.IO.Ports;
using MVSDK;
using MvApi = MVSDK.MvApi;
using CameraHandle = System.Int32;
using System.Threading;
using System.Runtime.InteropServices;

namespace test
{

    public partial class Form1 : Form
    {
        #region 变量定义
        private OmronFinsNet omronFinsNet = null;       //建立欧姆龙通讯

        protected CameraHandle m_hCamera = 0;             // 句柄
        protected IntPtr m_ImageBuffer;             // 预览通道RGB图像缓存
        protected IntPtr m_ImageBufferSnapshot;     // 抓拍通道RGB图像缓存
        protected tSdkCameraCapbility tCameraCapability;  // 相机特性描述
        protected int m_iDisplayedFrames = 0;    //已经显示的总帧数
        protected CAMERA_SNAP_PROC m_CaptureCallback;
        protected IntPtr m_iCaptureCallbackCtx;     //图像回调函数的上下文参数
        protected Thread m_tCaptureThread;          //图像抓取线程
        protected bool m_bExitCaptureThread = false;//采用线程采集时，让线程退出的标志
        protected IntPtr m_iSettingPageMsgCallbackCtx; //相机配置界面消息回调函数的上下文参数   
        protected tSdkFrameHead m_tFrameHead;
        protected SnapshotDlg m_DlgSnapshot = new SnapshotDlg();               //显示抓拍图像的窗口
        protected Settings m_DlgSettings = new Settings();
        protected bool m_bEraseBk = false;
        protected bool m_bSaveImage = false;
        #endregion
        public Form1()
        {
            InitializeComponent();
            MvApi.CameraPlay(m_hCamera);
            BtnPlay.Text = "停止";

        }

#if USE_CALL_BACK
        public void ImageCaptureCallback(CameraHandle hCamera, IntPtr pFrameBuffer, ref tSdkFrameHead pFrameHead, IntPtr pContext)
        {
            //图像处理，将原始输出转换为RGB格式的位图数据，同时叠加白平衡、饱和度、LUT等ISP处理。
            MvApi.CameraImageProcess(hCamera, pFrameBuffer, m_ImageBuffer, ref pFrameHead);
            //叠加十字线、自动曝光窗口、白平衡窗口信息(仅叠加设置为可见状态的)。   
            MvApi.CameraImageOverlay(hCamera, m_ImageBuffer, ref pFrameHead);
            //调用SDK封装好的接口，显示预览图像
            MvApi.CameraDisplayRGB24(hCamera, m_ImageBuffer, ref pFrameHead);
            m_tFrameHead = pFrameHead;
            m_iDisplayedFrames++;

            if (pFrameHead.iWidth != m_tFrameHead.iWidth || pFrameHead.iHeight != m_tFrameHead.iHeight)
            {
                timer2.Enabled = true;
                timer2.Start();
                m_tFrameHead = pFrameHead;
            }
            
        }
#else
        public void CaptureThreadProc()
        {
            CameraSdkStatus eStatus;
            tSdkFrameHead FrameHead;
            IntPtr uRawBuffer;//rawbuffer由SDK内部申请。应用层不要调用delete之类的释放函数

            while (m_bExitCaptureThread == false)
            {
                //500毫秒超时,图像没捕获到前，线程会被挂起,释放CPU，所以该线程中无需调用sleep
                eStatus = MvApi.CameraGetImageBuffer(m_hCamera, out FrameHead, out uRawBuffer, 500);

                if (eStatus == CameraSdkStatus.CAMERA_STATUS_SUCCESS)//如果是触发模式，则有可能超时
                {
                    //图像处理，将原始输出转换为RGB格式的位图数据，同时叠加白平衡、饱和度、LUT等ISP处理。
                    MvApi.CameraImageProcess(m_hCamera, uRawBuffer, m_ImageBuffer, ref FrameHead);
                    //叠加十字线、自动曝光窗口、白平衡窗口信息(仅叠加设置为可见状态的)。    
                    MvApi.CameraImageOverlay(m_hCamera, m_ImageBuffer, ref FrameHead);
                    //调用SDK封装好的接口，显示预览图像
                    MvApi.CameraDisplayRGB24(m_hCamera, m_ImageBuffer, ref FrameHead);
                    //成功调用CameraGetImageBuffer后必须释放，下次才能继续调用CameraGetImageBuffer捕获图像。
                    MvApi.CameraReleaseImageBuffer(m_hCamera, uRawBuffer);

                    if (FrameHead.iWidth != m_tFrameHead.iWidth || FrameHead.iHeight != m_tFrameHead.iHeight)
                    {
                        m_bEraseBk = true;
                        m_tFrameHead = FrameHead;
                    }

                    m_iDisplayedFrames++;

                    if (m_bSaveImage)
                    {
                        MvApi.CameraSaveImage(m_hCamera, "D:\\test.bmp", m_ImageBuffer, ref FrameHead, emSdkFileType.FILE_BMP, 100);
                        m_bSaveImage = false;
                    }
                }

            }

        }
#endif

        private bool InitCamera()
        {
            CameraSdkStatus status;
            tSdkCameraDevInfo[] tCameraDevInfoList;
            IntPtr ptr;
            int i;
#if USE_CALL_BACK
            CAMERA_SNAP_PROC pCaptureCallOld = null;
#endif
            if (m_hCamera > 0)
            {
                //已经初始化过，直接返回 true

                return true;
            }

            status = MvApi.CameraEnumerateDevice(out tCameraDevInfoList);
            if (status == CameraSdkStatus.CAMERA_STATUS_SUCCESS)
            {
                if (tCameraDevInfoList != null)//此时iCameraCounts返回了实际连接的相机个数。如果大于1，则初始化第一个相机
                {
                    status = MvApi.CameraInit(ref tCameraDevInfoList[0], -1, -1, ref m_hCamera);
                    if (status == CameraSdkStatus.CAMERA_STATUS_SUCCESS)
                    {
                        //获得相机特性描述
                        MvApi.CameraGetCapability(m_hCamera, out tCameraCapability);

                        m_ImageBuffer = Marshal.AllocHGlobal(tCameraCapability.sResolutionRange.iWidthMax * tCameraCapability.sResolutionRange.iHeightMax * 3 + 1024);
                        m_ImageBufferSnapshot = Marshal.AllocHGlobal(tCameraCapability.sResolutionRange.iWidthMax * tCameraCapability.sResolutionRange.iHeightMax * 3 + 1024);

                        if (tCameraCapability.sIspCapacity.bMonoSensor != 0)
                        {
                            // 黑白相机输出8位灰度数据
                            MvApi.CameraSetIspOutFormat(m_hCamera, (uint)MVSDK.emImageFormat.CAMERA_MEDIA_TYPE_MONO8);
                        }

                        //初始化显示模块，使用SDK内部封装好的显示接口
                        MvApi.CameraDisplayInit(m_hCamera, PreviewBox.Handle);
                        MvApi.CameraSetDisplaySize(m_hCamera, PreviewBox.Width, PreviewBox.Height);

                        //设置抓拍通道的分辨率。
                        tSdkImageResolution tResolution;
                        tResolution.uSkipMode = 0;
                        tResolution.uBinAverageMode = 0;
                        tResolution.uBinSumMode = 0;
                        tResolution.uResampleMask = 0;
                        tResolution.iVOffsetFOV = 0;
                        tResolution.iHOffsetFOV = 0;
                        tResolution.iWidthFOV = tCameraCapability.sResolutionRange.iWidthMax;
                        tResolution.iHeightFOV = tCameraCapability.sResolutionRange.iHeightMax;
                        tResolution.iWidth = tResolution.iWidthFOV;
                        tResolution.iHeight = tResolution.iHeightFOV;
                        //tResolution.iIndex = 0xff;表示自定义分辨率,如果tResolution.iWidth和tResolution.iHeight
                        //定义为0，则表示跟随预览通道的分辨率进行抓拍。抓拍通道的分辨率可以动态更改。
                        //本例中将抓拍分辨率固定为最大分辨率。
                        tResolution.iIndex = 0xff;
                        tResolution.acDescription = new byte[32];//描述信息可以不设置
                        tResolution.iWidthZoomHd = 0;
                        tResolution.iHeightZoomHd = 0;
                        tResolution.iWidthZoomSw = 0;
                        tResolution.iHeightZoomSw = 0;

                        MvApi.CameraSetResolutionForSnap(m_hCamera, ref tResolution);

                        //让SDK来根据相机的型号动态创建该相机的配置窗口。
                        MvApi.CameraCreateSettingPage(m_hCamera, this.Handle, tCameraDevInfoList[0].acFriendlyName,/*SettingPageMsgCalBack*/null,/*m_iSettingPageMsgCallbackCtx*/(IntPtr)null, 0);

                        //两种方式来获得预览图像，设置回调函数或者使用定时器或者独立线程的方式，
                        //主动调用CameraGetImageBuffer接口来抓图。
                        //本例中仅演示了两种的方式,注意，两种方式也可以同时使用，但是在回调函数中，
                        //不要使用CameraGetImageBuffer，否则会造成死锁现象。
#if USE_CALL_BACK
                        m_CaptureCallback = new CAMERA_SNAP_PROC(ImageCaptureCallback);
                        MvApi.CameraSetCallbackFunction(m_hCamera, m_CaptureCallback, m_iCaptureCallbackCtx, ref pCaptureCallOld);
#else //如果需要采用多线程，使用下面的方式
                        m_bExitCaptureThread = false;
                        m_tCaptureThread = new Thread(new ThreadStart(CaptureThreadProc));
                        m_tCaptureThread.Start();

#endif
                        //MvApi.CameraReadSN 和 MvApi.CameraWriteSN 用于从相机中读写用户自定义的序列号或者其他数据，32个字节
                        //MvApi.CameraSaveUserData 和 MvApi.CameraLoadUserData用于从相机中读取自定义数据，512个字节


                        m_DlgSettings.m_hCamera = m_hCamera;
                        return true;

                    }
                    else
                    {
                        m_hCamera = 0;
                        StateLabel.Text = "Camera init error";
                        String errstr = string.Format("相机初始化错误，错误码{0},错误原因是", status);
                        String errstring = MvApi.CameraGetErrorString(status);
                        // string str1 
                        MessageBox.Show(errstr + errstring, "ERROR");
                        Environment.Exit(0);
                        return false;
                    }


                }
            }
            else
            {
                MessageBox.Show("没有找到相机，如果已经接上相机，可能是权限不够，请尝试使用管理员权限运行程序。");
                Environment.Exit(0);
            }

            return false;

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.DataSource = HslCommunication.BasicFramework.SoftBasic.GetEnumValues<HslCommunication.Core.DataFormat>();
            comboBox1.SelectedItem = HslCommunication.Core.DataFormat.CDAB;
            //panel2.Enabled = false;



            //RegistryKey keyCom = Registry.LocalMachine.OpenSubKey(@"HARDWARE\DEVICEMAP\SERIALCOMM ");
            //string[] svalue = keyCom.GetValueNames();
            //comboBox2.Items.Clear();
            //foreach( var temp in svalue)
            //{
            //    comboBox2.Items.Add(temp);
            //}


        }

        double length;
        double width;
        double getarea;

        public void Acceptdetails()
        {
            length = 7.5;
            width = 3.5;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            dynamic s = 20.2;

            Console.WriteLine("你好");
            Acceptdetails();
            getarea = length * width;
            MessageBox.Show(getarea.ToString());
        }

        private void BT1_Click_Click(object sender, EventArgs e)
        {
            const long a = 11l;
            uint b = 220u;
            long c = 8l;
            b += b;
            c = a == 12 ? 2 : 13;
            Console.WriteLine("a = {0},b = {1},c = {2}", a % 2, b, c);


        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            Int32 f;
            //f = Data_A.Text.ToInt32();
            //f=(string)Data_A.Text
            f = Convert.ToInt32(Data_A.Text);
            if (Convert.ToInt32(Data_A.Text) > Convert.ToInt32(Data_B.Text))
            {
                Display.Text = "A>B";
            }
            else if
                (Convert.ToInt32(Data_A.Text) == Convert.ToInt32(Data_B.Text))
            {
                Display.Text = "A=B";
            }
            else
            {
                Display.Text = "A<B";
            }

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void Data_B_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (Convert.ToInt32(Data_A.Text) > Convert.ToInt32(Data_B.Text))
            {
                Display.Text = "A>B";
            }
            else if
                (Convert.ToInt32(Data_A.Text) == Convert.ToInt32(Data_B.Text))
            {
                Display.Text = "A=B";
            }
            else
            {
                Display.Text = "A<B";
            }
        }

        private void label4_Click(object sender, EventArgs e)
        {

        }

        private void A_addres_TextChanged(object sender, EventArgs e)
        {

        }

        private void BT_JMP_Click(object sender, EventArgs e)
        {
            if (checkedListBox1.GetItemChecked(0))
            {
                listBox_display.Items.Clear();
                listBox_display.Items.Add("EMG");
            }
            else if (checkedListBox1.GetItemChecked(1))
            {
                listBox_display.Items.Clear();
                listBox_display.Items.Add("NG");
            }
            else if (checkedListBox1.GetItemChecked(2))
            {
                screen sc = new screen();
                sc.Show();
            }
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            groupBox4.Enabled = true;
            try
            {
                if (!serialPort1.IsOpen)
                {
                    serialPort1.PortName = comboBox2.Text;//端口号
                    serialPort1.BaudRate = Convert.ToInt32(comboBox1.Text.Trim());//波特率
                    serialPort1.DataBits = Convert.ToInt32(tbDataLen.Text.Trim());//数据位
                    switch (comboBoxParity.Text.Trim())//奇偶校验
                    {
                        case "N":
                            serialPort1.Parity = System.IO.Ports.Parity.None;
                            break;
                        case "O":
                            serialPort1.Parity = System.IO.Ports.Parity.Odd;
                            break;
                        case "E":
                            serialPort1.Parity = System.IO.Ports.Parity.Even;
                            break;
                        default:
                            serialPort1.Parity = System.IO.Ports.Parity.None;
                            break;

                    }
                    switch (Convert.ToDouble(comboBoxStopbit.Text.Trim()))
                    {
                        case 1:
                            serialPort1.StopBits = System.IO.Ports.StopBits.One;
                            break;
                        case 1.5:
                            serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
                            break;
                        case 2:
                            serialPort1.StopBits = System.IO.Ports.StopBits.Two;
                            break;
                        default:
                            serialPort1.StopBits = System.IO.Ports.StopBits.One;
                            break;

                    }
                    serialPort1.Open();
                    btnConnect.Text = "断开";
                }
                else
                {
                    serialPort1.Close();
                    btnConnect.Text = "连接";
                }


                if (serialPort1.IsOpen)
                {
                    MessageBox.Show("连接成功");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnTCPConnect_Click(object sender, EventArgs e)
        {

            string ip = tbIPAddress.Text.Trim();
            //验证IP格式
            bool check = Regex.IsMatch(ip, @"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
            if (!check)
            {
                MessageBox.Show("格式输入错误\r\n参照如下格式\r\n“192.168.1.1”", "提醒了哈");
                return;
            }

            if (!int.TryParse(tbPortnum.Text, out int port))       //转换端口号的值到port中
            {
                MessageBox.Show("端口号错误");
                return;
            }

            if (!byte.TryParse(tbNetnum.Text, out byte SA1))
            {
                MessageBox.Show("本机网络号错误");
                return;
            }

            if (!byte.TryParse(tbPlcnum.Text, out byte DA2))
            {
                MessageBox.Show("单元号错误");
                return;
            }

            omronFinsNet.IpAddress = tbIPAddress.Text;
            omronFinsNet.Port = port;
            omronFinsNet.SA1 = SA1;
            omronFinsNet.DA2 = DA2; //PLC单元号
                                    // omronFinsNet.ByteTransform.DataFormat = HslCommunication.Core.DataFormat.CDAB;

            OperateResult connect = omronFinsNet.ConnectServer();       //返回结果
            if (connect.IsSuccess)
            {
                MessageBox.Show("恭喜，连接成功了");
                btnTCPConnectOff.Enabled = true;
                btnTCPConnect.Enabled = false;
                groupBox4.Enabled = true;

                //userControlCurve1.ReadWriteNet = omronFinsNet;
            }
            else
            {
                MessageBox.Show(HslCommunication.StringResources.Language.ConnectedFailed);
            }
        }

        private void BtnPlay_Click(object sender, EventArgs e)
        {
            if (m_hCamera < 1)//还未初始化相机
            {
                if (InitCamera() == true)
                {
                    MvApi.CameraPlay(m_hCamera);
                    BtnPlay.Text = "Pause";
                }
            }
            else//已经初始化
            {
                if (BtnPlay.Text == "Play")
                {
                    MvApi.CameraPlay(m_hCamera);
                    BtnPlay.Text = "Pause";
                }
                else
                {
                    MvApi.CameraPause(m_hCamera);
                    BtnPlay.Text = "Play";
                }
            }
        }

        private void BtnSettings_Click(object sender, EventArgs e)
        {
            if (m_hCamera > 0)
            {
                m_DlgSettings.Show();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            var cities = new Dictionary<string, string>()
            {
                {"UK", "London, Manchester, Birmingham"},
                {"USA", "Chicago, New York, Washington"},
                {"India", "Mumbai, New Delhi, Pune"}
            };
            cities.Add("France", "Paris, Marseilles, Lyon");

            Console.WriteLine(cities["UK"]); //打印 UK 键值
            if (cities.ContainsKey("France"))
            {
                Console.WriteLine(cities["France"]);
            }
        }

    }

 
}
